#include "processwrapper.h"

#include <QtCore>

#ifdef Q_OS_WIN32

#include <windows.h>
#include <stdio.h>
#include <psapi.h>

unsigned int ProcessWrapper::currentProcessId()
{
  return GetCurrentProcessId();
}

unsigned int ProcessWrapper::findProcess(const char *name, unsigned int pid_skip)
{
    DWORD aProcesses[1024], cbNeeded, cProcesses;
    unsigned int i;
    QString pname(name); pname += ".exe";

    if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
        return 0;

    // Calculate how many process identifiers were returned.

    cProcesses = cbNeeded / sizeof(DWORD);

    // Print the name and process identifier for each process.

    for ( i = 0; i < cProcesses; i++ )
    {
        unsigned int processID = aProcesses[i];
    if( processID != 0 && processID != pid_skip )
        {
            char szProcessName[MAX_PATH] = "<unknown>";

            // Get a handle to the process.

            HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
                                           PROCESS_VM_READ,
                                           FALSE, processID );

            // Get the process name.

            if (NULL != hProcess )
            {
                HMODULE hMod;
                DWORD cbNeeded;

                if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
                     &cbNeeded) )
                {
                    GetModuleBaseNameA( hProcess, hMod, szProcessName,
                                       sizeof(szProcessName)/sizeof(TCHAR) );

                    if (QString(szProcessName) == pname)
                    {
                        CloseHandle( hProcess );
                        return processID;
                    }
                }

                CloseHandle( hProcess );
            }

            // Print the process name and identifier.

            //_tprintf( TEXT("%s  (PID: %u)\n"), szProcessName, processID );

        }
    }

    return 0;
}

bool ProcessWrapper::terminateProcess(unsigned int pid, int wait)
{
  HANDLE hProcess = OpenProcess( PROCESS_TERMINATE | SYNCHRONIZE,
                                 FALSE, pid );

  if (hProcess == NULL)
    return false;

  TerminateProcess(hProcess, 0);

  WaitForSingleObject(hProcess, wait);

  return true;
}

bool ProcessWrapper::activateProcess(unsigned int pid_)
{
  HWND h = ::GetTopWindow(0);
  while ( h )
  {
    DWORD pid;
    ::GetWindowThreadProcessId( h, &pid );

     if ( pid == pid_ )
     {
        SetActiveWindow(h);
        return SetForegroundWindow(h);
        //return SwitchToThisWindow(h,false);
     }
     h = ::GetNextWindow( h, GW_HWNDNEXT );
  }
  return false;
}

bool ProcessWrapper::sendMessage(unsigned int pid_, unsigned int msg_,
                                 unsigned int param1_, unsigned int param2_)
{
  HWND h = ::GetTopWindow(0);
  while ( h )
  {
    DWORD pid;
    ::GetWindowThreadProcessId( h, &pid );

     if ( pid == pid_ )
     {
       return PostMessage(h, msg_, param1_, param2_);
     }

     h = ::GetNextWindow( h, GW_HWNDNEXT );
  }
  return false;
}

#else

unsigned int ProcessWrapper::currentProcessId()
{
    return getpid();
}

unsigned int ProcessWrapper::findProcess(const char *name, unsigned int pid_skip)
{
    QString pname("(" + QString(name) + ")");
    QDir pd("/proc");
    QFileInfoList list = pd.entryInfoList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
    QFileInfoList::iterator it, it_end = list.end();
    for (it = list.begin(); it != it_end; it++)
    {
        const QFileInfo &fi = *it;
        if (fi.baseName().at(0).isDigit()) {
            QFile f(fi.absoluteFilePath()+"/stat");
            if (f.open(QIODevice::ReadOnly)) {
                QTextStream ts(&f);
                unsigned int pid; ts >> pid;
                if (pid == pid_skip)
                    continue;
                QString pn; ts >> pn;
                if (pn == pname)
                    return pid;
            }
        }
    }

    return 0;
}

#endif


ProcessWrapper::ProcessWrapper()
{
}

